package tacos.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Qualifier("userRepositoryUserDetailsService")
    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder encoder() {
        // encoder()方法带有@Bean注解，它将用来在Spring上下文中声明PasswordEncoder Bean,对于encoder()的任何调用都会被拦截，并且会返回应用上下文中的bean实例
        return new StandardPasswordEncoder("53cr3t");
    }

//    @Override  // 基于内存的配置存贮
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.inMemoryAuthentication().withUser("buzz").password("infinity").authorities("ROLE_USER").and()
//                .withUser("woody").password("bullseye").authorities("ROLE_USER");
//    }

    @Override  // 将自定义的用户详情服务userDetailsService 与Spring Security配置在一起,并将自动装配到SecurityConfig中的UserDetailsService实例传递了进去
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 配置密码转码器，这样数据库中的密码将是转码过的
        auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
    }

    @Override  // 配置安全性规则
    protected void configure(HttpSecurity http) throws Exception {
        // 配置Web级别如何处理安全性
        // 1.在为某个请求提供服务之前，需要与现年满足特定的条件
        // 2.配置自定义的登录页
        // 3.支持用户退出应用
        // 4.预防跨站请求伪造
        // 拦截请求，确保用户权限（确保只有认证过的用户才能发起对 /design 和 /orders 的请求,其他请求对所有用户均可用）
        // 声明在前面的安全规则比后面的规则有更高的优先级，如果交换顺序，则所有的请求都会具有permitAll的规则，对/design和/orders的声明规则就不会生效了
        // 除了hasRole和permitAll的其他方法，参见p101
//        http.authorizeRequests().antMatchers("/design", "/orders").hasRole("USER").antMatchers("/", "/**").permitAll()
//                .and().formLogin().loginPage("/login").and().logout().logoutSuccessUrl("/");
        http.csrf().disable();  // 关闭csrf校验
        http.authorizeRequests().antMatchers("/", "/**").permitAll();
    }
}
